﻿using System;
using System.Collections.Generic;
using RentalSystem.Data.EF.Core;
using System.Data.Objects;

namespace RentalSystem.Data.EF.Dao
{
    public class EFUsersDao : IUsersDao
    {
        #region Queries

        private readonly string ListQuery;
        private readonly string ValidateUserQuery;
        private readonly string GetByEmailQuery;
        private readonly string GetUserAndCustomerQuery;
        private readonly string GetByIdQuery;

        #endregion

        private EFManager<Users> manager;

        public EFUsersDao(RentalDatabaseEntities repository)
        {
            ListQuery = "SELECT VALUE u FROM Users AS u;";
            ValidateUserQuery = "SELECT VALUE user FROM Users AS user WHERE user.UserEmail = @Email AND user.UserPassword=@Password;";
            GetByEmailQuery = "SELECT VALUE user FROM Users AS user WHERE user.UserEmail = @Email;";
            GetByIdQuery = "SELECT VALUE user FROM Users AS user WHERE user.UserGuid = @Guid;";

            this.manager = new EFManager<Users>(repository);
        }

        #region IDao1Key

        public Users Add(Users entity)
        {
            manager.Database.AddToUsers(entity);
            manager.Save();
            return entity;
        }

        public Users Get(string id)
        {
            QueryParam[] parameters = new QueryParam[]
                {
                    new QueryParam("@Guid", id)
                };

            var users = manager.SQLQueryToEntity(GetByIdQuery, parameters);

            foreach (Users user in users)
            {
                return user;
            }

            return null;
        }

        public void Delete(string id)
        {
            Users user = Get(id);

            if (user == null) return;

            manager.Database.Users.DeleteObject(user);
            manager.Save();
        }

        public void Delete(Users entity)
        {
            this.Delete(entity.UserGuid);
        }

        public void Update(Users entity, uint fields)
        {
            Users fromDb = Get(entity.UserGuid);

            if (fromDb != null)
            {
                if ((fields & (uint)UserFields.Agency) == (uint)UserFields.Agency)
                    fromDb.AgencyId = entity.AgencyId;
                if ((fields & (uint)UserFields.Customer) == (uint)UserFields.Customer)
                    fromDb.CustomerGuid = entity.CustomerGuid;
                if ((fields & (uint)UserFields.DateCreated) == (uint)UserFields.DateCreated)
                    fromDb.UserDateCreated = entity.UserDateCreated;
                if ((fields & (uint)UserFields.DisplayName) == (uint)UserFields.DisplayName)
                    fromDb.UserDisplayName = entity.UserDisplayName;
                if ((fields & (uint)UserFields.Email) == (uint)UserFields.Email)
                    fromDb.UserEmail = entity.UserEmail;
                if ((fields & (uint)UserFields.IsAccountActive) == (uint)UserFields.IsAccountActive)
                    fromDb.UserAccountIsActive = entity.UserAccountIsActive;
                if ((fields & (uint)UserFields.IsNewsletterActive) == (uint)UserFields.IsNewsletterActive)
                    fromDb.UserIsNewsletterActive = entity.UserIsNewsletterActive;
                if ((fields & (uint)UserFields.LastLoginDate) == (uint)UserFields.LastLoginDate)
                    fromDb.UserLastLoginDate = entity.UserLastLoginDate;
                if ((fields & (uint)UserFields.LastLoginIp) == (uint)UserFields.LastLoginIp)
                    fromDb.UserLastLoginIP = entity.UserLastLoginIP;
                if ((fields & (uint)UserFields.PasswordHash) == (uint)UserFields.PasswordHash)
                    if(!string.IsNullOrEmpty(entity.UserPassword))
                        fromDb.UserPassword = entity.UserPassword;
                if ((fields & (uint)UserFields.Role) == (uint)UserFields.Role)
                    fromDb.UserRoleID = entity.UserRoleID;
                if ((fields & (uint)UserFields.Worker) == (uint)UserFields.Worker)
                    fromDb.WorkerGuid = entity.WorkerGuid;
            }
            manager.Save();
        }

        public List<Users> List()
        {
            List<Users> list = new List<Users>();

            var users = manager.SQLQueryToEntity(ListQuery);

            foreach (Users user in users)
            {
                list.Add(user);
            }

            return list;
        }

        #endregion

        public Users GetByEmail(string email)
        {
            QueryParam[] parameters = new QueryParam[]
                {
                    new QueryParam("@Email", email)
                };

            var users = manager.SQLQueryToEntity(GetByEmailQuery, parameters);

            foreach (Users user in users)
            {
                return user;
            }

            return null;
        }

        public Users ValidateUser(string userEmail, string passwordHash)
        {
            QueryParam[] parameters = new QueryParam[]
                {
                    new QueryParam("@Email", userEmail),
                    new QueryParam("@Password", passwordHash)
                };

            var users = manager.SQLQueryToEntity(ValidateUserQuery, parameters);

            foreach (Users user in users)
            {
                return user;
            }

            return null;
        }

        public UserRoles GetUserRole(string userEmail)
        {
            QueryParam[] parameters = new QueryParam[]
                {
                    new QueryParam("@Email", userEmail)
                };

            var users = manager.SQLQueryToEntity(GetByEmailQuery, parameters);

            foreach (Users user in users)
            {
                return user.UserRoles;
            }

            return null;
        }
    }
}
